function deepClone(source) {
    if (source === null || source === undefined || source === 0 || !isNaN(source)) {
        return source;
    }
    if (source.constructor === String || source.constructor === Boolean) {
        return source;
    }
    if (source.constructor === Date) {
        return new Date(source);
    }
    let target = source.constructor === Array ? [] : {};
    if (source.constructor === Object) {
        for (let key in source) {
            if (source.hasOwnProperty(key)) {
                if (source[key].constructor === Object) {
                    target[key] = deepClone(source[key]);
                } else {
                    target[key] = source[key];
                }
            }
        }
    } else if (source.constructor === Array) {
        for (let i = 0; i < source.length; i++) {
            target.push(deepClone(source[i]));
        }
    }
    return target;
}

module.exports = deepClone;